#include "regex.h"
#include "regex_p.h"

// for test
int test_run(FILE* pfRegex, char* pcDataFile)
{
	FILE* pfData = NULL;
	char acLine[1024];
    char acRegex[1024];
    struct regex_all_t stRegex;
    char* pcRegex = NULL;

    while (fgets(acRegex, sizeof(acRegex), pfRegex) != NULL)	
    {
        if (acRegex[0] == '#')
            continue;

        memset(&stRegex, 0, sizeof(stRegex));
        if (acRegex[strlen(acRegex)-1] == '\n')
            acRegex[strlen(acRegex)-1] = 0;
        if (acRegex[strlen(acRegex)-1] == '\r')
            acRegex[strlen(acRegex)-1] = 0;

        printf("regex:%s\n", acRegex);

        pcRegex = malloc(strlen(acRegex) + 3);
        if (pcRegex == NULL)
        {
            printf("malloc error.\n");
            return -1;
        } 
        memset(pcRegex, 0, strlen(acRegex) + 3);

        *pcRegex = '(';
        if (acRegex[0] == MATCH_START)
        {
            stRegex.cHead = TRUE;
            strcat(pcRegex, acRegex+1);
        } 
        else
        {
            strcat(pcRegex, acRegex);
        } 
        strcat(pcRegex, ")");

        if (analyse_all(pcRegex, &stRegex.pstRegex) == NULL)
        {
            printf("%s %d:regex error.(%s)\n", __func__, __LINE__, pcRegex);
            return -1;
        } 
        free(pcRegex);
        pcRegex = NULL;

        // out put regex
        printf("Original Regex:%s\n", acRegex);
        printf("Regex:");
        print_regex(stRegex.pstRegex);
        printf("\n");
        print_regex_tree(stRegex.pstRegex);

        // test data file open
		pfData = fopen(pcDataFile, "r+");
		if (pfData == NULL)
		{
			printf("File(%s) open error.(%s)\n", pcDataFile, strerror(errno));
			return -1;
		} 
		while (fgets(acLine, sizeof(acLine), pfData) != NULL)	
		{
            if (acLine[0] == '#')
                continue;

            acLine[strlen(acLine)-1] = 0;
			if (match_all(acLine, &stRegex))
			{
			} 
            printf("\n");
		} 

		fclose(pfData);
        free_regex(stRegex.pstRegex);
    } 

    return 0;
} 

int get_param(int argc, char* argv[], FILE** ppfRegex, char* pcTestData)
{
	int iRet = 0;
    char opt;
    char acRegexFile[256];
    FILE* pfRegex = NULL;

    memset(acRegexFile, 0, sizeof(acRegexFile));

    if (argc == 3)
    {
        pfRegex = tmpfile();
        if (pfRegex == NULL)
        {
            printf("make regex file error.(%s)", strerror(errno));
            return -1;
        } 
        iRet = fputs(argv[1], pfRegex);
        if (iRet == EOF)
        {
            printf("write regex file error.(%s)", strerror(errno));
            return -1;
        } 
        fflush(pfRegex);
        rewind(pfRegex);

        strncpy(pcTestData, argv[2], 255);
    } 
    else
    {
        while ((opt = getopt(argc, argv, "f:")) != -1)
        {
            switch (opt)
            {
                case 'f':
                    strncpy(acRegexFile, optarg, sizeof(acRegexFile)-1);
                    break;
                case '?':
                    if (optopt == 'f')
                    {
                        printf("-f need parameter.\n");
                        return -1;
                    } 
                    break;
                default:
                    break;
            } 
        } 
        strncpy(pcTestData, argv[optind], 255);

        if (acRegexFile[0] == 0)
        {
            printf("Check param please.\n");
            return -1;
        } 

        pfRegex = fopen(acRegexFile, "r+");
        if (pfRegex == NULL)
        {
            printf("open regex file error.(%s)", strerror(errno));
            return -1;
        } 
    } 

    *ppfRegex = pfRegex;

    return 0;
} 

void output_matchinfo(struct match_info_t* pstMatchInfo)
{
    struct match_info_t* pstCur = NULL;

    pstCur = pstMatchInfo;
    while (pstCur)
    {
        printf("Match Str: %.*s\n", 
                (int)(pstCur->pcMatchEnd-pstCur->pcMatchStart), 
                pstCur->pcMatchStart);
        pstCur = pstCur->pstNext;
    } 

    return;
} 

void free_matchinfo(struct match_info_t* pstMatchInfo)
{
    struct match_info_t* pstCur = NULL;
    struct match_info_t* pstNext = NULL;

    pstCur = pstMatchInfo;
    while (pstCur)    
    {
        pstNext = pstCur->pstNext;
        free(pstCur);
        pstCur = pstNext;
    } 

    return;
} 

// example for match function
int test_match(FILE* pfRegex, char* pcDataFile)
{
	FILE* pfData = NULL;
	char acLine[1024];
    char acRegex[1024];
    struct match_info_t* pstMatchInfo = NULL;

    // test data file open
    pfData = fopen(pcDataFile, "r+");
    if (pfData == NULL)
    {
        printf("File(%s) open error.(%s)\n", pcDataFile, strerror(errno));
        return -1;
    } 
    while (fgets(acRegex, sizeof(acRegex), pfRegex) != NULL)	
    {
        if (acRegex[0] == '#')
            continue;

        if (acRegex[strlen(acRegex)-1] == '\n')
            acRegex[strlen(acRegex)-1] = 0;
        if (acRegex[strlen(acRegex)-1] == '\r')
            acRegex[strlen(acRegex)-1] = 0;

        printf("\nregex:%s\n", acRegex);

        rewind(pfData);
		while (fgets(acLine, sizeof(acLine), pfData) != NULL)	
		{
            if (acLine[0] == '#')
                continue;

            acLine[strlen(acLine)-1] = 0;
            pstMatchInfo = NULL;
			if (match(acRegex, acLine, &pstMatchInfo))
			{
                output_matchinfo(pstMatchInfo);
			} 
            free_matchinfo(pstMatchInfo);
		} 
    } 
    fclose(pfData);

    return 0;
} 

int main(int argc, char *argv[])  
{
	int iRet = 0;
    FILE* pfRegex = NULL;
    char acTestData[256];

    memset(acTestData, 0, sizeof(acTestData));

	if (argc < 3)
	{
		printf("Please check parameter.\n");
		return -1;
	} 

    iRet = get_param(argc, argv, &pfRegex, acTestData);
    if (iRet != 0)
    {
        return -1;
    } 
    //iRet = test_run(pfRegex, acTestData);
    test_match(pfRegex, acTestData);

    fclose(pfRegex);
    return iRet;
} 

